/*
 * Object.h
 *
 *  Created on: Aug 5, 2013
 *      Author: alexandru
 */

#include <stdlib.h>
#include <string>
#include <vector>
#include <sstream>

#include <fstream>
#include <dirent.h>
#include <sys/stat.h>
#include <boost/filesystem.hpp>
#include <curl/curl.h>
#include "Utils.h"
#include  "Query.h"
#include  "Error.h"

#ifndef OBJECT_H_
#define OBJECT_H_




#define FUNC_EXIT "exit()"
#define FUNC_TO_JSON "toJson()"
#define FUNC_GET_JSON_VALUE "getJsonValue()"
#define FUNC_SAVE "save()"
#define FUNC_GET_NAME "getName()"
#define FUNC_SET_NAME "setName("

#define DB_EXTENSION ".json"


namespace stn {





struct XmlStruct{

	std::string nodeNameLine;
	std::string attributesLine;
	std::string attributesBlock;

	std::string nodeName;
	std::string innerContent;
	std::vector<std::string> strVec;
	std::vector<stn::SimpleStruct> xmlAttributes;
	int tosp;

	void convertData(){
		using namespace std;
		using boost::is_any_of;


		boost::algorithm::trim(attributesLine);
		boost::algorithm::trim(nodeNameLine);

		boost::algorithm::split(strVec, attributesLine, is_any_of("\t "),boost::token_compress_on);




		if((int)strVec.size()>0){
			nodeName=strVec.at(0);
			boost::algorithm::trim(nodeName);

			if(nodeName.length()<=0){
				nodeName=UTILS_STR_UNDEFINED;
			}

		}else{
			nodeName=UTILS_STR_UNDEFINED;
		}



//		size_t index=nodeNameLine.find(attributesLine);
		size_t firstEnd=nodeNameLine.find_first_of(UTILS_CHAR_BIGGER);

		if (firstEnd!=string::npos){
//			tosp=index+attributesLine.length()+firstEnd;
			tosp=firstEnd+1;

			if(tosp < (int)nodeNameLine.length()){
				innerContent=nodeNameLine.substr(tosp);
				boost::algorithm::trim(innerContent);
			}else{
				innerContent=UTILS_STR_NULL;
			}
		}else{
			innerContent=UTILS_STR_NULL;
		}


		size_t found=attributesLine.find(nodeName);

		if(found!=std::string::npos){
			tosp=found+nodeName.length()+1;
			if(tosp < (int)attributesLine.length()){
				attributesBlock=attributesLine.substr(found+nodeName.length()+1);
				boost::algorithm::trim(attributesBlock);
			}else{
				attributesBlock=UTILS_STR_NULL;
			}
		}else{
			attributesBlock=UTILS_STR_NULL;
		}


		xmlAttributes=Utils::convertToSimpleStruct(attributesBlock);

	}

	void describe(){
		convertData();
		using namespace std;
		cout << "NODE NAME LINE: " << nodeNameLine << endl;
		cout << "ATTRIBUTES LINE: " << attributesLine << endl;
		cout << "ATTRIBUTES BLOCK: " << attributesBlock << endl;
		cout << "NODE NAME: " << nodeName << endl;
		cout << "INNER CONTENT: " << innerContent << endl;
		cout << "XMLATTRIBUTES SIZE: " << xmlAttributes.size() << endl;

		for(int i=0; i< (int) xmlAttributes.size(); i++){
				cout  << UTILS_CHAR_AT << xmlAttributes.at(i).property <<  "="<< xmlAttributes.at(i).value << endl;
			}

		cout << "   " << endl;
	}
};//exit xmlStruct


//template <typename T, typename I>
//T* iterator_to_pointer(I i)
//{
//	return (&(*i));
//}


class Object {


private:
		std::vector<Object> objectList;
		std::string propName;
		std::string StringType;
		double NumberType;
		bool BooleanType;
		/*
		 * 1 - String
		 * 2 - Number
		 * 3 - Boolean
		 * 4 - Object
		 * 5 - Array
		 * */
		std::string result;
		int PROP_TYPE;
		int ind;


		//utile in lucru:
		int nrAcol;
			int nrPaDr;
			bool iPr;
			bool skip;
			std::string propNamT;
			std::string propValT;
			char c; //current analized char

		struct tempObject{
			std::string name;
			std::string prop;
		};

		std::vector<tempObject> listaTemp;

		std::string tstr;

		//utile in query
		int modified;
			int deleted;




			std::string workingDir;



			void traceXmlStruct();


public:




		bool isRoot;


		std::string prefix;

		static int MODE_STRING;
		static int MODE_NUM;
		static int MODE_BOOL;
		static int MODE_OBJ;
		static int MODE_ARR;

		 typedef struct{
				int min;
				int max;
			}range;

		void setType(int mode);
		int getType();
		void setName(std::string str);
		std::string getName();


		void addObject(Object object);
		void push(Object *object);

		Object getByIndex(std::string index);
		Object getByName(std::string objPropName);

		Object * getInstanceByName(std:: string objPropName, bool loose);
		Object * getInstanceByIndex(std:: string objPropName);



		void removeAtIndex(int index);
		void removeAtIndex(std::string index);


		void setWorkingDir(std::string dirName);
		void saveToFile();
		void loadFromFile();
		void loadDb(std::string dbName);


		void importFolderStruct(std::string pathStr);
		void importRemoteXml(std::string pathStr);
		void importLocalXml(std::string location, bool htmlModeOn);




		Object * runQuery(std::string query);

				bool validIs_Operator(std::string oper);
                bool validIs_NumericComparison(std::string numComp);
                bool validIs_modInRange(int number, range rata);
                bool validIs_type(std::string type);
                bool validIs_StringComparison(std::string strComp);

                bool compareNumeric(int one, int two, std::string command);
                bool compareStrings(std::string pov, std::string input, std::string command);



                //utile la query numeric
                		int numModifed;
                		range between;
                		range toRange(std::string arg);


                



                Object * useValuesNumeric(std::string value, std::string action, std::string comparison, std::string updateValue);

                Object * useDataStrings(std::string dataType, std::string comparisonTerm, std::string comparison, std::string action, std::string updateValue);
                std::string getDataByType(std::string type, Object object);





                //TODO de implementat metodele de output
		std::string  toJson();
		const char * toJsonBeauty(std::string strPre);
		std::string  toXML();
		const char * toXMLBeauty();
		const char * getJsonValue();
		std::string getStringValue();

		typedef struct{
					int numeric;
					bool boolean;
					std::string charList;
				}RealVal;
		RealVal getRealValue();

		inline bool IsNumber(char c);

		void setValue(std::string str);


		void convertObject(std::string str);
		void convertArray(std::string str);


		Object(const char * ppropName, const char * pValue);
		Object(const char * ppropName, double pdNumber);
		Object(const char * ppropName, int pdNumber);
		Object(const char * ppropName, bool pbolValue);
		Object(const char * ppropName);
		Object(const char * ppropName, std::string strVal);
		Object(Error * eroare);
		Object(XmlStruct * xmlStruct);
		Object * commandResponse;

	Object();
	virtual ~Object();


	std::string runCommand(std::string command);

	void parseXML(std::string input);

};

} /* namespace stn */
#endif /* OBJECT_H_ */
